import axios from 'axios';
import type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse } from 'axios';

// ============ 类型定义 ============
interface QueueItem {
  resolve: (value: unknown) => void;
  reject: (reason?: any) => void;
}

// ============ Token 存储管理类 ============
class TokenManager {
  private static readonly TOKEN_KEY = 'token';
  private static readonly REFRESH_TOKEN_KEY = 'refreshToken';

  static get(): string | null {
    return localStorage.getItem(this.TOKEN_KEY);
  }

  static set(token: string): void {
    localStorage.setItem(this.TOKEN_KEY, token);
  }

  static remove(): void {
    localStorage.removeItem(this.TOKEN_KEY);
  }

  static getRefreshToken(): string | null {
    return localStorage.getItem(this.REFRESH_TOKEN_KEY);
  }

  static setRefreshToken(token: string): void {
    localStorage.setItem(this.REFRESH_TOKEN_KEY, token);
  }

  static removeRefreshToken(): void {
    localStorage.removeItem(this.REFRESH_TOKEN_KEY);
  }

  static clearAll(): void {
    this.remove();
    this.removeRefreshToken();
  }
}

// ============ 请求队列管理类 ============
class RequestQueue {
  private queue: QueueItem[] = [];
  private isProcessing = false;

  get isRefreshing(): boolean {
    return this.isProcessing;
  }

  setRefreshing(status: boolean): void {
    this.isProcessing = status;
  }

  add(): Promise<unknown> {
    return new Promise((resolve, reject) => {
      this.queue.push({ resolve, reject });
    });
  }

  process(error: any, token: string | null | undefined): void {
    this.queue.forEach(item => {
      error ? item.reject(error) : item.resolve(token);
    });
    this.clear();
  }

  clear(): void {
    this.queue = [];
  }
}

// ============ Token 刷新管理类 ============
class TokenRefreshManager {
  private queue: RequestQueue;

  constructor(queue: RequestQueue) {
    this.queue = queue;
  }

  async executeWithLock<T>(callback: () => Promise<T>): Promise<T> {
    this.queue.setRefreshing(true);
    try {
      const result = await callback();
      this.queue.setRefreshing(false);
      return result;
    } catch (error) {
      this.queue.setRefreshing(false);
      throw error;
    }
  }

  async autoLogin(): Promise<string> {
    const response = await axios.post('/api/login', {
      username: 'defaultUser',
      password: 'defaultPassword'
    });
    const token = response.data.data.token;
    TokenManager.set(token);
    return token;
  }

  async refreshToken(): Promise<string> {
    const refreshToken = TokenManager.getRefreshToken();
    const response = await axios.post('/api/refreshToken', { refreshToken });
    const newToken = response.data.token;
    TokenManager.set(newToken);
    return newToken;
  }

  handleRefreshFailed(): void {
    TokenManager.clearAll();
    // window.location.href = '/login';
  }
}

// ============ HTTP 请求拦截器管理类 ============
class RequestInterceptorManager {
  private queue: RequestQueue;
  private refreshManager: TokenRefreshManager;

  constructor(queue: RequestQueue, refreshManager: TokenRefreshManager) {
    this.queue = queue;
    this.refreshManager = refreshManager;
  }

  private setAuthorizationHeader(config: InternalAxiosRequestConfig, token: string | null): InternalAxiosRequestConfig {
    if (token && config.headers) {
      config.headers.Authorization = token;
    }
    return config;
  }

  private async handleQueuedRequest(config: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> {
    try {
      const token = await this.queue.add();
      return this.setAuthorizationHeader(config, token as string);
    } catch (error) {
      return Promise.reject(error);
    }
  }

  async handleRequest(config: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> {
    // 登录接口不需要token
    if (config.url === '/api/login') {
      return config;
    }

    let token = TokenManager.get();

    // 如果没有token且不在刷新token的过程中
    if (!token && !this.queue.isRefreshing) {
      try {
        token = await this.refreshManager.executeWithLock(() => this.refreshManager.autoLogin());
        this.queue.process(null, token);
      } catch (error) {
        this.queue.process(error, null);
        return Promise.reject(error);
      }
    }

    // 如果正在刷新token，将请求加入队列
    if (this.queue.isRefreshing) {
      return this.handleQueuedRequest(config);
    }

    // 有token直接设置
    return this.setAuthorizationHeader(config, token);
  }
}

// ============ HTTP 响应拦截器管理类 ============
class ResponseInterceptorManager {
  private queue: RequestQueue;
  private refreshManager: TokenRefreshManager;
  private axiosInstance: AxiosInstance;

  constructor(queue: RequestQueue, refreshManager: TokenRefreshManager, axiosInstance: AxiosInstance) {
    this.queue = queue;
    this.refreshManager = refreshManager;
    this.axiosInstance = axiosInstance;
  }

  private setAuthorizationHeader(config: any, token: string): void {
    if (config.headers) {
      config.headers.Authorization = token;
    }
  }

  private shouldRefreshToken(error: any, originalRequest: any): boolean {
    return (
      error.response?.status === 401 &&
      !originalRequest.url.includes('/login') &&
      !originalRequest._retry
    );
  }

  private async retryRequest(originalRequest: any, token: string): Promise<any> {
    this.setAuthorizationHeader(originalRequest, token);
    return this.axiosInstance(originalRequest);
  }

  private async handle401Response(originalRequest: any): Promise<any> {
    // 如果正在刷新token，将请求加入队列
    if (this.queue.isRefreshing) {
      const token = await this.queue.add();
      return this.retryRequest(originalRequest, token as string);
    }

    // 标记为已重试，防止无限循环
    originalRequest._retry = true;

    try {
      const newToken = await this.refreshManager.executeWithLock(() => this.refreshManager.refreshToken());
      this.queue.process(null, newToken);
      return this.retryRequest(originalRequest, newToken);
    } catch (error) {
      this.queue.process(error, null);
      this.refreshManager.handleRefreshFailed();
      return Promise.reject(error);
    }
  }

  handleSuccess(response: AxiosResponse): any {
    return response.data;
  }

  async handleError(error: any): Promise<any> {
    const originalRequest = error.config;

    // 如果是401错误且不是登录请求，尝试刷新token
    if (this.shouldRefreshToken(error, originalRequest)) {
      return this.handle401Response(originalRequest);
    }

    return Promise.reject(error);
  }
}

// ============ HTTP 请求客户端类 ============
class HttpClient {
  private axiosInstance: AxiosInstance;
  private requestQueue: RequestQueue;
  private refreshManager: TokenRefreshManager;
  private requestInterceptor: RequestInterceptorManager;
  private responseInterceptor: ResponseInterceptorManager;

  constructor(baseURL: string = '/api', timeout: number = 10000) {
    // 创建 axios 实例
    this.axiosInstance = axios.create({
      baseURL,
      timeout,
    });

    // 初始化管理器
    this.requestQueue = new RequestQueue();
    this.refreshManager = new TokenRefreshManager(this.requestQueue);
    this.requestInterceptor = new RequestInterceptorManager(this.requestQueue, this.refreshManager);
    this.responseInterceptor = new ResponseInterceptorManager(this.requestQueue, this.refreshManager, this.axiosInstance);

    // 设置拦截器
    this.setupInterceptors();
  }

  private setupInterceptors(): void {
    // 请求拦截器
    this.axiosInstance.interceptors.request.use(
      (config) => this.requestInterceptor.handleRequest(config),
      (error) => Promise.reject(error)
    );

    // 响应拦截器
    this.axiosInstance.interceptors.response.use(
      (response) => this.responseInterceptor.handleSuccess(response),
      (error) => this.responseInterceptor.handleError(error)
    );
  }

  getInstance(): AxiosInstance {
    return this.axiosInstance;
  }
}

// ============ 创建实例并导出 ============
const httpClient = new HttpClient();
const request = httpClient.getInstance();

export { request, TokenManager, HttpClient };
export default request;